#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Dec 26 01:39:39 2019

@author: bing
"""
 
from flask import Flask, render_template,redirect, request, jsonify
from werkzeug.utils import secure_filename
import os
import cv2
import time
from myUtil import parse_result, isFakePlate
from datetime import timedelta
import pandas as pd
import numpy as np
import darknet as dn
from hyperlpr import HyperLPR_PlateRecogntion as plateRecog  # 车牌识别库
from keras.preprocessing.image import img_to_array
from keras.models import load_model


#设置允许的文件格式
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'JPG', 'PNG', 'bmp'])

#vehicle_info_database = pd.read_csv('vehicle-database.csv')
cwd_path = os.getcwd()
cfg_path = cwd_path + "/cfg/yolov3-voc.cfg"
weights_path = cwd_path + "/cfg/yolov3-voc_final.weights"
data_path = cwd_path + "/cfg/voc.data"

VEHICLE_WIDTH = 28
VEHICLE_HEIGHT = 28
v_color_model_path = cwd_path + "/cfg/vehicle_color.hdf5" #
v_type_model_path = cwd_path + "/cfg/vehicle_type.hdf5"

global vehicle_info_database,net,meta

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS

 
def prepare_service():
    global vehicle_info_database
    # 
    vehicle_info_database = pd.read_csv('vehicle-database.csv')
   
    return vehicle_info_database
    
# 预测模块，输入图片，分析车牌信息和子品牌，跟车辆信息库对比查询，判定是否为嫌疑车辆
def predict(imgPath, vehicle_info_database):
    predictResult = "未识别"
    plateNo = "未识别"
    carBrandZh = "未识别"
    original_image = cv2.imread(imgPath)
 #加载配置文件和权重
    net = dn.load_net(cfg_path.encode('utf-8'), weights_path.encode('utf-8'), 0)
    meta = dn.load_meta(data_path.encode('utf-8'))
    
    v_color_model = load_model(v_color_model_path)
    v_type_model = load_model(v_type_model_path)
    
  

    predict_result_dict = dn.detect(net, meta, imgPath.encode('utf-8'))
    
    result_dict = parse_result(predict_result_dict) # 结果进行后处理
    
    for i in range(result_dict["b_box_num"]):
        
        x1_min = result_dict["detection_boxes"][i][0]
        y1_min = result_dict["detection_boxes"][i][1]
        
        x1_max = result_dict["detection_boxes"][i][2]
        y1_max = result_dict["detection_boxes"][i][3]
        carBrandZh = result_dict["detection_classes"][i] # 在线模型输出直接是中文字符串，而之前的离线模型是ascii编码的字符串
     
       # 截取汽车检测框的下面1/3部分，作为车牌检测的子区域。调用车牌识别，准确率和计算速度有保证
        left = x1_min
        top = int(y1_min + (y1_max - y1_min)*0.67)
        right = x1_max
        bottom = y1_max
        crop_image = original_image[top:bottom, left:right]
        grayImg = cv2.cvtColor(crop_image, cv2.COLOR_BGR2GRAY)
        roi_img = cv2.resize(grayImg, (VEHICLE_WIDTH, VEHICLE_HEIGHT))
        roi_img = roi_img.astype("float")/255.0
        roi_img = img_to_array(roi_img)
        roi_img = np.expand_dims(roi_img, axis=0)
        (bus,car,minibus,truck) = v_type_model.predict(roi_img)[0]
        v_type_result = {"bus":bus,"car":car,"minibus":minibus,"truck":truck}
        v_type_label = max(v_type_result,key=v_type_result.get)
        
        (black,blue,brown,green,red,silver,white,yellow ) = v_color_model.predict(roi_img)[0]
        v_color_result = {"black":black,"blue": blue, "brown":brown, "green":green, "red": red, "silver":silver,"white":white,"yellow":yellow}
        v_color_label = max(v_color_result, key=v_color_result.get)
        
        plateInfo = plateRecog(crop_image)
        if plateInfo:
            plateNo = plateInfo[0][0]
            inputCarInfo = [plateNo, carBrandZh]
            # print(inputCarInfo)
            isFake, true_car_brand = isFakePlate(inputCarInfo, vehicle_info_database)
            if isFake:
               predictResult = "这是一辆套牌车" 
            else:
               predictResult = "这是一辆正常车"    
        else:
            plateNo = "未识别"
            #carBrandZh = "未识别"
            predictResult = "车牌未识别，无法判定" 
            
    return plateNo, v_type_label, v_color_label, carBrandZh, predictResult
# ------------------------------------------------------------------------------------------------------------------------
app = Flask(__name__)
# 设置静态文件缓存过期时间
app.send_file_max_age_default = timedelta(seconds=1)
vehicle_info_database = prepare_service()

@app.route('/prepare')
def warm_up():
    vehicle_info_database = prepare_service()
    return redirect('/')


@app.route('/', methods=['POST', 'GET'])  # 添加路由
def analyze():
    if request.method == 'POST':
        f = request.files['file']
 
        if not (f and allowed_file(f.filename)):
            return jsonify({"error": 1001, "msg": "请检查上传的图片类型，仅限于png、PNG、jpg、JPG、bmp"})
 
        basepath = os.path.dirname(__file__)  # 当前文件所在路径
       
        upload_path = os.path.join(basepath, 'static/images', secure_filename(f.filename))  # 注意：没有的文件夹一定要先创建，不然会提示没有该路径
  
        f.save(upload_path)
          
        # 使用Opencv转换一下图片格式和名称
        img = cv2.imread(upload_path)
        cv2.imwrite(os.path.join(basepath, 'static/images', 'test.jpg'), img)
        img_path = 'static/images/test.jpg'
        plate_no,v_type,v_color,car_brand, predict_result = predict(img_path, vehicle_info_database)
        context = ["车牌号："+plate_no,"车型："+ v_type,"车辆颜色："+v_color, "车辆品牌："+car_brand, "结论："+predict_result]
        
        return render_template('index.html', context = context, val1=time.time())
 
    return render_template('index.html')
 
 
if __name__ == '__main__':
    # app.debug = True
    app.run(port=8090, debug=True)
